#include "pzem.h"
#include "main.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

extern UART_HandleTypeDef huart3;

float Voltage;        // 电压
float Current;        // 电流
float ActivePower;    // 有功功率
float ElectricEnergy; // 电能
float Frequency;      // 频率
float PowerFactor;    // 功率因数

#define RX_BUFFER_SIZE 25
static uint8_t rx_pzem_buffer[RX_BUFFER_SIZE];

// CRC16校验函数
static uint16_t CRC16_MudBus(uint8_t *puchMsg, uint8_t usDataLen)
{
    uint16_t uCRC = 0xffff; // CRC寄存器

    for (uint8_t num = 0; num < usDataLen; num++)
    {
        uCRC = (*puchMsg++) ^ uCRC; // 把数据与16位的CRC寄存器的低8位相异或，结果存放于CRC寄存器。
        for (uint8_t x = 0; x < 8; x++)
        {
            // 循环8次
            if (uCRC & 0x0001) // 判断最低位为：“1”
            {
                uCRC = uCRC >> 1;     // 先右移
                uCRC = uCRC ^ 0xA001; // 再与0xA001异或
            }
            else
            {                     // 判断最低位为：“0”
                uCRC = uCRC >> 1; // 右移
            }
        }
    }
    return uCRC; // 返回CRC校验值
}

/* 数据发送和接收函数 */
bool Energy_assessment(void)
{
    uint8_t command[] = {0xf8, 0x04, 0x00, 0x00, 0x00, 0x0A, 0x64, 0x64};
    // 阻塞发送指令
    HAL_StatusTypeDef tx_status = HAL_UART_Transmit(&huart3, command, 8, HAL_MAX_DELAY);
    if (tx_status != HAL_OK)
    {
        return false;
    }
    // 阻塞接收25个字节，最长等待时间1秒
    HAL_StatusTypeDef rx_status = HAL_UART_Receive(&huart3, rx_pzem_buffer, RX_BUFFER_SIZE, 1000);
    if (rx_status != HAL_OK)
    {
        return false;
    }
    uint16_t crc;
    crc = CRC16_MudBus(rx_pzem_buffer, 23);
    if (crc == ((rx_pzem_buffer[24] << 8) | rx_pzem_buffer[23]))
    {
        Voltage = ((rx_pzem_buffer[3] << 8) + rx_pzem_buffer[4]) * 0.1;                                                                    // 电压
        Current = ((rx_pzem_buffer[7] << 24) + (rx_pzem_buffer[8] << 16) + (rx_pzem_buffer[5] << 8) + rx_pzem_buffer[6]) * 0.001;          // 电流
        ActivePower = ((rx_pzem_buffer[11] << 24) + (rx_pzem_buffer[12] << 16) + (rx_pzem_buffer[9] << 8) + rx_pzem_buffer[10]) * 0.1;     // 有功功率
        ElectricEnergy = ((rx_pzem_buffer[15] << 24) + (rx_pzem_buffer[16] << 16) + (rx_pzem_buffer[13] << 8) + rx_pzem_buffer[14]) * 0.1; // 电能
        Frequency = ((rx_pzem_buffer[17] << 8) + rx_pzem_buffer[18]) * 0.1;                                                                // 频率
        PowerFactor = ((rx_pzem_buffer[19] << 8) + rx_pzem_buffer[20]) * 0.01;                                                             // 功率因数
    }
    else
    {
        return false;
    }
    return true;
}
